# -*- coding: utf-8 -*-

import base64
import io
import logging
from odoo import models, fields, api, _
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)

try:
    import openpyxl
    from openpyxl.drawing.image import Image as ExcelImage
    from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
except ImportError:
    _logger.warning('openpyxl module not found, BOM export will not work')
    openpyxl = None


class CpqBomExportWizard(models.TransientModel):
    """BOM导出向导 - 支持导出带图片的Excel"""
    _name = 'cpq.bom.export.wizard'
    _description = 'BOM导出向导'

    bom_id = fields.Many2one(
        'cpq.bom',
        string='BOM版本',
        required=True,
        default=lambda self: self.env.context.get('active_id')
    )
    
    export_format = fields.Selection([
        ('xiaomi', '小米格式'),
        ('benz', '奔驰格式'),
        ('simple', '简化格式')
    ], string='导出格式', default='xiaomi', required=True)
    
    include_pictures = fields.Boolean(
        string='包含图片',
        default=True,
        help='是否在Excel中包含图片'
    )
    
    file_data = fields.Binary(
        string='导出文件',
        readonly=True
    )
    file_name = fields.Char(
        string='文件名',
        readonly=True
    )
    
    state = fields.Selection([
        ('draft', '准备'),
        ('done', '完成')
    ], default='draft')

    def action_export(self):
        """执行导出"""
        self.ensure_one()
        
        if not openpyxl:
            raise UserError(_('缺少openpyxl模块，请联系管理员安装'))
        
        if not self.bom_id:
            raise UserError(_('请选择要导出的BOM版本'))
        
        try:
            # 创建Excel工作簿
            wb = openpyxl.Workbook()
            ws = wb.active
            ws.title = 'BOM清单'
            
            # 根据格式导出
            if self.export_format == 'xiaomi':
                self._export_xiaomi_format(ws)
            elif self.export_format == 'benz':
                self._export_benz_format(ws)
            else:
                self._export_simple_format(ws)
            
            # 保存到内存
            output = io.BytesIO()
            wb.save(output)
            output.seek(0)
            
            # 转换为base64
            file_data = base64.b64encode(output.read())
            file_name = f'{self.bom_id.name}_导出_{fields.Datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx'
            
            self.write({
                'state': 'done',
                'file_data': file_data,
                'file_name': file_name
            })
            
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'cpq.bom.export.wizard',
                'view_mode': 'form',
                'res_id': self.id,
                'target': 'new',
            }
            
        except Exception as e:
            _logger.exception('BOM导出失败')
            raise UserError(_('导出失败: %s') % str(e))
    
    def _export_xiaomi_format(self, worksheet):
        """导出小米格式"""
        # 设置列宽
        column_widths = {
            'A': 12, 'B': 18, 'C': 30, 'D': 20, 'E': 12, 'F': 10,
            'G': 10, 'H': 18, 'I': 18, 'J': 18, 'K': 18, 'L': 15,
            'M': 20, 'N': 12, 'O': 10, 'P': 12, 'Q': 30, 'S': 8
        }
        for col, width in column_widths.items():
            worksheet.column_dimensions[col].width = width
        
        # 标题行（第1-2行）
        worksheet.merge_cells('A1:N1')
        title_cell = worksheet['A1']
        title_cell.value = f'{self.bom_id.name}\n{self.bom_id.name} BOM LIST'
        title_cell.font = Font(size=14, bold=True)
        title_cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
        
        worksheet['O1'] = '编号No.:'
        worksheet['P1'] = self.bom_id.project_id.code or ''
        worksheet['O2'] = '版本Rev.：'
        worksheet['P2'] = self.bom_id.version_name or ''
        
        # 表头行（第4行）
        headers = [
            '序号\nNo.',
            '零件号\nPart No.',
            '零件名称\nPart Name',
            '图片\nPicture',
            '配置及数量\nOptional & QTY',
            '总成级别\nAss.level',
            '零件状态\nStatus',
            '生产工艺\nProcess',
            '表面处理\nSurface',
            '表面处理标准\nSurface standard',
            '材料名称\nMaterial',
            '材料标准\nMaterial SPC',
            '外形尺寸\n长X×宽Y×高Z\nPart Size mm',
            '涂装面积\nSuface Area ㎡',
            '壁厚\nThickness\nmm',
            '参考净重量\nWeight\nkg',
            '备注\nRemark',
            '',  # R列
            'P/L',
        ]
        
        for idx, header in enumerate(headers, start=1):
            cell = worksheet.cell(row=4, column=idx)
            cell.value = header
            cell.font = Font(bold=True, size=10)
            cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
            cell.fill = PatternFill(start_color='D3D3D3', end_color='D3D3D3', fill_type='solid')
            cell.border = Border(
                left=Side(style='thin'),
                right=Side(style='thin'),
                top=Side(style='thin'),
                bottom=Side(style='thin')
            )
        
        # 设置表头行高
        worksheet.row_dimensions[4].height = 45
        
        # 数据行（从第6行开始）
        row_idx = 6
        for line in self.bom_id.line_ids.sorted(key=lambda l: l.sequence):
            # 列A: 序号
            worksheet.cell(row=row_idx, column=1).value = line.level_number
            # 列B: 零件号
            worksheet.cell(row=row_idx, column=2).value = line.part_number or ''
            # 列C: 零件名称
            worksheet.cell(row=row_idx, column=3).value = line.part_name or ''
            
            # 列D: 图片
            if self.include_pictures and line.picture:
                try:
                    # 使用 PIL 库获取图片信息以便调整尺寸
                    from PIL import Image as PILImage
                    
                    # 处理 base64 数据
                    # Odoo的Binary字段返回的是bytes，需要先解码为字符串
                    if isinstance(line.picture, bytes):
                        raw_base64 = line.picture.decode('utf-8')
                    else:
                        raw_base64 = line.picture
                    
                    # 检查并移除常见的数据 URI 前缀 (如 data:image/png;base64,)
                    if ',' in raw_base64:
                        raw_base64 = raw_base64.split(',', 1)[-1]
                    
                    # 解码 base64 图片数据
                    img_data = base64.b64decode(raw_base64)
                    img_stream = io.BytesIO(img_data)
                    
                    # 使用 PIL 打开图片获取原始尺寸
                    pil_img = PILImage.open(img_stream)
                    original_width, original_height = pil_img.size
                    
                    # 根据单元格大小计算图片尺寸
                    # 行高: 40磅 ≈ 53像素 (40 * 1.33)
                    # 列宽: 20字符 ≈ 140像素 (经验值: 1字符宽度 ≈ 7像素)
                    CELL_HEIGHT_PIXELS = int(40 * 1.33)  # 约53像素
                    CELL_WIDTH_PIXELS = int(20 * 7)      # 约140像素
                    
                    # 留一些边距，避免图片超出单元格
                    MAX_HEIGHT = CELL_HEIGHT_PIXELS - 4  # 约49像素
                    MAX_WIDTH = CELL_WIDTH_PIXELS - 4    # 约136像素
                    
                    # 等比例缩放，以高度和宽度中较小的缩放比例为准
                    height_ratio = MAX_HEIGHT / original_height if original_height > MAX_HEIGHT else 1
                    width_ratio = MAX_WIDTH / original_width if original_width > MAX_WIDTH else 1
                    ratio = min(height_ratio, width_ratio)
                    
                    new_width = int(original_width * ratio)
                    new_height = int(original_height * ratio)
                    
                    # 重新定位stream到开始
                    img_stream.seek(0)
                    
                    # 创建Excel图片对象
                    excel_img = ExcelImage(img_stream)
                    excel_img.width = new_width
                    excel_img.height = new_height
                    
                    # 设置行高为40磅（与原始导入的Excel保持一致）
                    worksheet.row_dimensions[row_idx].height = 40
                    
                    # 将图片锚定到目标单元格
                    cell_coordinate = worksheet.cell(row=row_idx, column=4).coordinate
                    excel_img.anchor = cell_coordinate
                    
                    # 插入图片
                    worksheet.add_image(excel_img)
                    
                    # 成功插入图片后，单元格保持为空（让图片显示）
                    # 不要写入文本，否则图片会覆盖文本
                    
                    _logger.info(f'导出图片成功: 行{row_idx}, 尺寸:{new_width}x{new_height}, 原始:{original_width}x{original_height}')
                except Exception as e:
                    _logger.warning(f'插入图片失败 (行{row_idx}): {e}')
                    import traceback
                    _logger.warning(traceback.format_exc())
                    # 仅在失败时写入错误提示
                    worksheet.cell(row=row_idx, column=4).value = '[图片错误]'
            
            # 列E: 配置及数量
            worksheet.cell(row=row_idx, column=5).value = line.configuration or ''
            # 列F: 总成级别
            worksheet.cell(row=row_idx, column=6).value = line.assembly_level or ''
            # 列G: 零件状态
            status_map = {'new': 'NEW', 'carryover': 'CARRYOVER', 'modified': 'MODIFIED'}
            worksheet.cell(row=row_idx, column=7).value = status_map.get(line.part_status, '')
            # 列H: 生产工艺
            process_map = {
                'injection': '注塑',
                'painting': '喷漆',
                'injection_painting': '注塑+喷漆',
                'assembly': '装配',
                'metal': '金属冲压',
                'foam': '发泡',
                'other': '其他'
            }
            worksheet.cell(row=row_idx, column=8).value = process_map.get(line.process_type, '')
            # 列I: 表面处理
            worksheet.cell(row=row_idx, column=9).value = line.surface_treatment or ''
            # 列J: 表面处理标准
            worksheet.cell(row=row_idx, column=10).value = line.surface_standard or ''
            # 列K: 材料名称
            worksheet.cell(row=row_idx, column=11).value = line.material or ''
            # 列L: 材料标准
            worksheet.cell(row=row_idx, column=12).value = line.material_standard or ''
            # 列M: 外形尺寸
            worksheet.cell(row=row_idx, column=13).value = line.dimensions or ''
            # 列N: 涂装面积
            worksheet.cell(row=row_idx, column=14).value = line.surface_area or ''
            # 列O: 壁厚
            worksheet.cell(row=row_idx, column=15).value = line.thickness or ''
            # 列P: 重量（从g转换为kg）
            if line.weight:
                worksheet.cell(row=row_idx, column=16).value = line.weight / 1000
            # 列Q: 备注
            worksheet.cell(row=row_idx, column=17).value = line.notes or ''
            # 列S: P/L
            worksheet.cell(row=row_idx, column=19).value = line.make_or_buy or ''
            
            row_idx += 1
    
    def _export_benz_format(self, worksheet):
        """导出奔驰格式（待实现）"""
        # TODO: 实现奔驰格式导出
        self._export_simple_format(worksheet)
    
    def _export_simple_format(self, worksheet):
        """导出简化格式"""
        # 简化格式：只包含核心字段
        headers = ['序号', '零件号', '零件名称', '材料', '重量(kg)', 'L/P', '备注']
        
        for idx, header in enumerate(headers, start=1):
            cell = worksheet.cell(row=1, column=idx)
            cell.value = header
            cell.font = Font(bold=True)
        
        row_idx = 2
        for line in self.bom_id.line_ids.sorted(key=lambda l: l.sequence):
            worksheet.cell(row=row_idx, column=1).value = line.level_number
            worksheet.cell(row=row_idx, column=2).value = line.part_number or ''
            worksheet.cell(row=row_idx, column=3).value = line.part_name or ''
            worksheet.cell(row=row_idx, column=4).value = line.material or ''
            if line.weight:
                worksheet.cell(row=row_idx, column=5).value = line.weight / 1000
            worksheet.cell(row=row_idx, column=6).value = line.make_or_buy or ''
            worksheet.cell(row=row_idx, column=7).value = line.notes or ''
            
            row_idx += 1
